﻿#Region "Imports"

Imports System.DirectoryServices

#End Region

Friend Module IIsHelper

#Region "Constants"

    Public Const IIsProviderPath = "IIS://LocalHost"
    Public Const ServiceSchemaClassName = "IIsWebService"
    Public Const SiteSchemaClassName = "IIsWebServer"
    Public Const VirtualDirectorySchemaClassName = "IIsWebVirtualDir"
    Public Const DirectorySchemaClassName = "IIsWebDirectory"
    Public Const FileSchemaClassName = "IIsWebFile"
    Public Const ApplicationPoolsSchemaClassName = "IIsApplicationPools"
    Public Const ApplicationPoolSchemaClassName = "IIsApplicationPool"
    Public Const LocalMachineNamespace = "/LM"

#End Region

#Region "Functions and Methods"

    Public Function GetProperty(ByVal PropertyName As String, ByVal DirEntry As DirectoryEntry) As Object

        Try

            DirEntry.RefreshCache()

            If Not DirEntry.Properties(PropertyName).Value Is Nothing Then

                Return DirEntry.Properties(PropertyName).Value

            Else

                Return Nothing

            End If

        Catch ex As Exception

            GetPropertyEx(PropertyName, ex)
            Return Nothing

        End Try

    End Function

    Public Function GetPropertyA(ByVal PropertyName As String, ByVal DirEntry As DirectoryEntry) As Object()

        Try

            DirEntry.RefreshCache()

            If Not DirEntry.Properties(PropertyName).Value Is Nothing Then

                If DirEntry.Properties(PropertyName).Value.GetType.IsArray Then

                    Return DirEntry.Properties(PropertyName).Value

                Else

                    Return New Object() {DirEntry.Properties(PropertyName).Value}

                End If

            Else

                Return New Object() {}

            End If

        Catch ex As Exception

            GetPropertyEx(PropertyName, ex)
            Return New Object() {}

        End Try

    End Function

    Public Sub GetPropertyEx(ByVal PropertyName As String, ByVal Ex As Exception)

        Throw New Exception(String.Format("An error occured while trying to get the value of property '{0}'.", PropertyName), Ex)

    End Sub

    Public Sub SetProperty(ByVal PropertyName As String, ByVal PropertyValue As Object, ByVal DirEntry As DirectoryEntry)

        Try

            If DirEntry.Properties(PropertyName).Value Is Nothing Then

                DirEntry.Properties(PropertyName).Value = PropertyValue

            Else

                DirEntry.Properties(PropertyName).Item(0) = PropertyValue

            End If

            DirEntry.CommitChanges()

        Catch ex As Exception

            SetPropertyEx(PropertyName, ex)

        End Try

    End Sub

    Public Sub SetPropertyA(ByVal PropertyName As String, ByVal PropertyValue As Object(), ByVal DirEntry As DirectoryEntry)

        Try

            If DirEntry.Properties(PropertyName).Value Is Nothing Then

                DirEntry.Properties(PropertyName).Value = PropertyValue

            Else

                DirEntry.Properties(PropertyName).Item(0) = PropertyValue

            End If

            DirEntry.CommitChanges()

        Catch ex As Exception

            SetPropertyEx(PropertyName, ex)

        End Try

    End Sub

    Public Sub SetPropertyEx(ByVal PropertyName As String, ByVal Ex As Exception)

        Throw New Exception(String.Format("An error occured while trying to set the value of property '{0}'.", PropertyName), Ex)

    End Sub

    Public Function GetScriptMaps(ByVal ApplicationPath As String) As ASPNETVersions

        GetScriptMaps = 0

        Try

            Dim SystemRoot = System.Environment.GetEnvironmentVariable("SystemRoot")
            Dim ServiceVersion As ASPNETVersions = ASPNETVersions.v1_1_4322
            Dim AppPath = ApplicationPath.Replace(IIsProviderPath & "/", String.Empty).Replace("\"c, "/"c) & "/"
            Dim ServicePath = AppPath.Split("/"c)(0) & "/"
            Dim Out As String = String.Empty

            Using p As New Process

                p.StartInfo.FileName = String.Format("{0}\Microsoft.NET\Framework\v1.1.4322\aspnet_regiis.exe", SystemRoot)
                p.StartInfo.Arguments = "-lk"
                p.StartInfo.CreateNoWindow = True
                p.StartInfo.UseShellExecute = False
                p.StartInfo.RedirectStandardOutput = True

                p.Start()
                p.WaitForExit()

                Out = p.StandardOutput.ReadToEnd

            End Using

            For Each s In Out.Split(New Char() {vbLf}, StringSplitOptions.RemoveEmptyEntries)

                If s.Split(vbTab)(0).ToLower = ServicePath.ToLower Then

                    If s.Split(vbTab)(1).StartsWith("1.1.4322") Then
                        ServiceVersion = ASPNETVersions.v1_1_4322
                    ElseIf s.Split(vbTab)(1).StartsWith("2.0.50727") Then
                        ServiceVersion = ASPNETVersions.v2_0_50727
                    ElseIf s.Split(vbTab)(1).StartsWith("4.0.30319") Then
                        ServiceVersion = ASPNETVersions.v4_0_30319
                    End If

                End If

                If s.Split(vbTab)(0).ToLower = AppPath.ToLower Then

                    If s.Split(vbTab)(1).StartsWith("1.1.4322") Then
                        GetScriptMaps = ASPNETVersions.v1_1_4322
                    ElseIf s.Split(vbTab)(1).StartsWith("2.0.50727") Then
                        GetScriptMaps = ASPNETVersions.v2_0_50727
                    ElseIf s.Split(vbTab)(1).StartsWith("4.0.30319") Then
                        GetScriptMaps = ASPNETVersions.v4_0_30319
                    End If

                End If

            Next

            If GetScriptMaps = 0 Then GetScriptMaps = ServiceVersion

        Catch ex As Exception

            GetPropertyEx("ASPNETVersion", ex)

        End Try

    End Function

    Public Sub SetScriptMaps(ByVal ApplicationPath As String, ByVal ASPNETVersion As ASPNETVersions)

        Try

            Dim SystemRoot = System.Environment.GetEnvironmentVariable("SystemRoot")
            Dim AppRoot = ApplicationPath.Replace(IIsProviderPath & "/", String.Empty)

            Using p As New Process

                Dim version As String = String.Empty

                Select Case ASPNETVersion
                    Case ASPNETVersions.v1_1_4322
                        version = "1.1.4322"
                    Case ASPNETVersions.v2_0_50727
                        version = "2.0.50727"
                    Case ASPNETVersions.v4_0_30319
                        version = "4.0.30319"
                End Select

                p.StartInfo.FileName = String.Format("{0}\Microsoft.NET\Framework\v{1}\aspnet_regiis.exe", SystemRoot, version)
                p.StartInfo.Arguments = String.Format("-norestart -s {0}", AppRoot)
                p.StartInfo.CreateNoWindow = True
                p.StartInfo.UseShellExecute = False

                p.Start()
                p.WaitForExit()

            End Using

        Catch ex As Exception

            SetPropertyEx("ASPNETVersion", ex)

        End Try

    End Sub

    Public Sub ConstructorEx(ByVal SchemaClassName As String)

        Throw New Exception(String.Format("The provided DirectoryEntry does not have the {0} SchemaClassName.", SchemaClassName))

    End Sub

#End Region

End Module
